package com.github.abel533.echarts.data;

import java.util.List;
import java.util.Map;




public class PrepareBoxplotData {
	private double[] boxData;
	private double[][] outliers;
	private double[] axisData;
	
	
	
	/*public PrepareBoxplotData prepareBoxplotData(double[][] rawData,double[] axisData,Object boundIQR){
		double[] opt ;
		double[] boxData  = new double[5];
		double[][] outliers = new double[rawData.length][2];
		double useExtreme = (double) boundIQR;
		for (int i = 0; i < rawData.length; i++) {
			double[] ascList = NumberUtil.asc(rawData[i]);
			double Q1 = NumberUtil.quantile(ascList, 0.25);
			double Q2 = NumberUtil.quantile(ascList, 0.5);
			double Q3 = NumberUtil.quantile(ascList, 0.75);
			double min = ascList[0];
			double max = ascList[ascList.length - 1];
			if(boundIQR ==null){
				boundIQR = 1.5;
			}
			double bound = (double)boundIQR * (Q3 - Q1);
			double low = useExtreme!=0 ? min : Math.max(min, Q1 - bound);
			double high = useExtreme!=0 ? max : Math.min(max, Q3 + bound);
			boxData[0]=low;
			boxData[1]=Q1;
			boxData[2]=Q2;
			boxData[3]=Q3;
			boxData[4]=high;
		    for (int j = 0; j < ascList.length; j++) {
		      double dataItem = ascList[j];

		      if (dataItem < low || dataItem > high) {
		    	  double[] outlier = {axisData[i], dataItem};
		        //opt.layout === 'vertical' && outlier.reverse();
		    	  outliers[i]= outlier;
		      }
		    }
		  }
		this.boxData = boxData;
		this.outliers = outliers;
		this.axisData = axisData;
		return this;
	}*/
	
	/*public double[] prepareBoxplotData(double[] rawData,String axisData,Object boundIQR){
		double[] opt ;
		double[] boxData  = new double[5];
		double[] outliers = new double[rawData.length];
		double useExtreme = (double) boundIQR;
		double[] ascList = NumberUtil.asc(rawData);
		double Q1 = NumberUtil.quantile(ascList, 0.25);
		double Q2 = NumberUtil.quantile(ascList, 0.5);
		double Q3 = NumberUtil.quantile(ascList, 0.75);
		double min = ascList[0];
		double max = ascList[ascList.length - 1];
		if(boundIQR ==null){
			boundIQR = 1.5;
		}
		double bound = (double)boundIQR * (Q3 - Q1);
		double low = useExtreme!=0 ? min : Math.max(min, Q1 - bound);
		double high = useExtreme!=0 ? max : Math.min(max, Q3 + bound);
		boxData[0]=low;
		boxData[1]=Q1;
		boxData[2]=Q2;
		boxData[3]=Q3;
		boxData[4]=high;
		return boxData;
	}*/
	public double[] prepareBoxplotData(List<Object> rawData,String axisData,Object boundIQR){
		double[] boxData  = new double[5];
		if(boundIQR ==null){
			boundIQR = 1.5;
		}
		double useExtreme = Double.parseDouble(boundIQR.toString());
		Object[] ascList = this.asc(rawData);
		double Q1 = this.quantile(ascList, 0.25);
		double Q2 = this.quantile(ascList, 0.5);
		double Q3 = this.quantile(ascList, 0.75);
		double min = Double.valueOf(ascList[0].toString());
		double max = Double.valueOf(ascList[ascList.length - 1].toString());
		
		double bound = Double.parseDouble(boundIQR.toString()) * (Q3 - Q1);
		double low = useExtreme!=0 ? min : Math.max(min, Q1 - bound);
		double high = useExtreme!=0 ? max : Math.min(max, Q3 + bound);
		boxData[0]=low;
		boxData[1]=Q1;
		boxData[2]=Q2;
		boxData[3]=Q3;
		boxData[4]=high;
		return boxData;
	}
	private Object[] asc(List<Object> list){
		int size = list.size();
		Object[] obj = new Object[size];
		for(int i = 0; i<size;i++){
			obj[i] = list.get(i);
		}
		return obj;
	}
	private double quantile(Object[] obj,double p){
		int len = obj.length;

        if (len==0) {
            return 0;
        }
        if (p <= 0 || len < 2) {
            return Double.parseDouble(obj[0].toString());
        }
        if (p >= 1) {
            return Double.parseDouble(obj[len -1].toString());
        }
        // in the wikipedia's R-7 method h = (N - 1)p + 1, but here array index start from 0
        double h = (len - 1) * p;
        int i = (int) Math.floor(h);
        double a = Double.parseDouble(obj[i].toString());
        double b = Double.parseDouble(obj[i + 1].toString());
        return a + (b - a) * (h - i);
	}
}
